pheatmap is a great R package for making heatmaps, inspiring a lot of other heatmap packages such as ComplexHeatmap. From version 2.5.2 of ComplexHeatmap, I implemented a new ComplexHeatmap::pheatmap() function which actually maps all the parameters in pheatmap::pheatmap() to proper parameters in ComplexHeatmap::Heatmap(), which means, it converts a pheatmap to a complex heatmap. By doing this, the most significant improvement is now you can add multiple pheatmaps and annotations (defined by ComplexHeatmap::rowAnnotation()).
ComplexHeatmap::pheatmap() includes all arguments in pheatmap::pheatmap(), which means, you don’t need to do any adaptation on your pheatmap code, you just rerun your pheatmap code and it will automatically and nicely convert to the complex heatmap.
Some arguments in pheatmap::pheatmap() are disabled and ignored in this translation, listed as follows:
kmeans_kfilenamewidthheightsilentThe usage of remaining arguments is exactly the same as in pheatmap::pheatmap().
In pheatmap::pheatmap(), the color argument is specified with a long color vector, e.g. :
pheatmap::pheatmap(mat,
color = colorRampPalette(rev(brewer.pal(n = 7, name = "RdYlBu")))(100)
)
You can use the same setting of color in ComplexHeatmap::pheatmap(), but you can also simplify it as:
ComplexHeatmap::pheatmap(mat,
color = rev(brewer.pal(n = 7, name = "RdYlBu"))
)
The colors for individual values are automatically interpolated.
First we load an example dataset which is from the “Examples” section of the documentation of pheatmap::pheatmap() function .
library(ComplexHeatmap)
test = matrix(rnorm(200), 20, 10)
test[1:10, seq(1, 10, 2)] = test[1:10, seq(1, 10, 2)] + 3
test[11:20, seq(2, 10, 2)] = test[11:20, seq(2, 10, 2)] + 2
test[15:20, seq(2, 10, 2)] = test[15:20, seq(2, 10, 2)] + 4
colnames(test) = paste("Test", 1:10, sep = "")
rownames(test) = paste("Gene", 1:20, sep = "")
Calling pheatmap() (which is now actually ComplexHeatmap::pheatmap()) generates a similar heatmap as by pheatmap::pheatmap().
pheatmap(test) # this is ComplexHeatmap::pheatmap
Everything looks the same except the style of the heatmap legend. There are also some other visual difference which you can find in the “Comparisons” section in this post.
The next one is an example for setting annotations (you should be familiar with how to set these data frames and color list if you are a pheatmap user).
annotation_col = data.frame(
CellType = factor(rep(c("CT1", "CT2"), 5)),
Time = 1:5
)
rownames(annotation_col) = paste("Test", 1:10, sep = "")
annotation_row = data.frame(
GeneClass = factor(rep(c("Path1", "Path2", "Path3"), c(10, 4, 6)))
)
rownames(annotation_row) = paste("Gene", 1:20, sep = "")
ann_colors = list(
Time = c("white", "firebrick"),
CellType = c(CT1 = "#1B9E77", CT2 = "#D95F02"),
GeneClass = c(Path1 = "#7570B3", Path2 = "#E7298A", Path3 = "#66A61E")
)
pheatmap(test, annotation_col = annotation_col, annotation_row = annotation_row,
annotation_colors = ann_colors)
You can split the heatmap by rows or by columns, which is a unique feature of ComplexHeatmap.
pheatmap(test, annotation_col = annotation_col, annotation_row = annotation_row,
annotation_colors = ann_colors,
row_split = annotation_row$GeneClass,
column_split = annotation_col$CellType)
ComplexHeatmap::pheatmap() returns a Heatmap object, so it can be added with other heatmaps and annotations. Or in other words, you can add multiple pheatmaps and annotations. Cool!
p1 = pheatmap(test, name = "mat1")
p2 = rowAnnotation(foo = anno_barplot(1:nrow(test)))
p3 = pheatmap(test, name = "mat2",
col = colorRampPalette(c("navy", "white", "firebrick3"))(50))
# or you can simply specify as
# p3 = pheatmap(test, name = "mat2", col = c("navy", "white", "firebrick3"))
p1 + p2 + p3
Nevertheless, if you really want to add multiple pheatmaps, I still suggest you to directly use the Heatmap() function. You can find how to migrate from pheatmap::pheatmap() to ComplexHeatmap::Heatmap() in the next section.
One last thing is since ComplexHeatmap::pheatmap() returns a Heatmap object, if pheatmap() is not called in an interactive environment, e.g. in an R script, inside a function or in a for loop, you need to explicitly use draw() function:
for(...) {
p = pheatmap(...)
draw(p)
}
Following table lists how to map parameters in pheatmap::pheatmap() to ComplexHeatmap::Heatmap().
Arguments in pheatmap::pheatmap() |
Identical settings/arguments in ComplexHeatmap::Heatmap() |
|---|---|
mat |
matrix |
color |
Users can specify a color mapping function by circlize::colorRamp2(), or provide a vector of colors on which colors for individual values are linearly interpolated. |
kmeans_k |
No corresponding parameter because it changes the matrix for heatmap. |
breaks |
It should be specified in the color mapping function. |
border_color |
rect_gp = gpar(col = border_color). In the annotations, it is HeatmapAnnotation(..., gp = gpar(col = border_color)). |
cellwidth |
width = ncol(mat)*unit(cellwidth, "pt") |
cellheight |
height = nrow(mat)*unit(cellheight, "pt") |
scale |
Users should simply apply scale() on the matrix before sending to Heatmap(). |
cluster_rows |
cluster_rows |
cluster_cols |
cluster_columns |
clustering_distance_rows |
clustering_distance_rows. The value correlation should be changed to pearson. |
clustering_distance_cols |
clustering_distance_columns, The value correlation should be changed to pearson. |
clustering_method |
clustering_method_rows/clustering_method_columns |
clustering_callback |
The processing on the dendrogram should be applied before sending to Heatmap(). |
cutree_rows |
row_split and row clustering should be applied. |
cutree_cols |
column_split and column clustering should be applied. |
treeheight_row |
row_dend_width = unit(treeheight_row, "pt") |
treeheight_col |
column_dend_height = unit(treeheight_col, "pt") |
legend |
show_heatmap_legend |
legend_breaks |
heatmap_legend_param = list(at = legend_breaks) |
legend_labels |
heatmap_legend_param = list(labels = legend_labels) |
annotation_row |
left_annotatioin = rowAnnotation(df = annotation_row) |
annotation_col |
top_annotation = HeatmapAnnotation(df = annotation_col) |
annotation |
Not supported. |
annotation_colors |
col argument in HeatmapAnnotation()/rowAnnotation(). |
annotation_legend |
show_legend argument in HeatmapAnnotation()/rowAnnotation(). |
annotation_names_row |
show_annotation_name in rowAnnotation(). |
annotation_names_col |
show_annotation_name in HeatmaoAnnotation(). |
drop_levels |
Unused levels are all dropped. |
show_rownames |
show_row_names |
show_colnames |
show_column_names |
main |
column_title |
fontsize |
gpar(fontsize = fontsize) in corresponding heatmap components. |
fontsize_row |
row_names_gp = gpar(fontsize = fontsize_row) |
fontsize_col |
column_names_gp = gpar(fontsize = fontsize_col) |
angle_col |
column_names_rot. The rotation of row annotation names are not supported. |
display_numbers |
Users should set a proper cell_fun or layer_fun (vectorized and faster version of cell_fun). E.g. if display_numbers is TRUE, layer_fun can be set as function(j, i, x, y, w, h, fill) { grid.text(sprintf(number_format, pindex(mat, i, j)), x = x, y = y, gp = gpar(col = number_color, fontsize = fontsize_number)) }. If display_numbers is a matrix, replace mat to display_numbers in the layer_fun. |
number_format |
See above. |
number_color |
See above. |
fontsize_number |
See above. |
gaps_row |
Users should construct a “splitting variable” and send to row_split. E.g. slices = diff(c(0, gaps_row, nrow(mat))); rep(seq_along(slices), times = slices). |
gaps_col |
Users should construct a “splitting variable” and send to column_split. |
labels_row |
row_labels |
labels_col |
column_labels |
filename |
No corresponding setting in Heatmap(). Users need to explicitly use e.g. pdf(). |
width |
No corresponding setting in Heatmap(). |
height |
No corresponding setting in Heatmap(). |
silent |
No corresponding setting in Heatmap(). |
na_col |
na_col |
I ran all the example code in the “Examples” section of the documentation of pheatmap::pheatmap() function . I also implemented a wrapper function ComplexHeatmap::compare_pheatmap() which basically uses the same set of arguments for pheatmap::pheatmap() and ComplexHeatmap::pheatmap() and draws two heatmaps, so that you can directly see the similarity and difference of the two heatmap implementations.
compare_pheatmap(test)
compare_pheatmap(test, scale = "row", clustering_distance_rows = "correlation")
compare_pheatmap(test,
color = colorRampPalette(c("navy", "white", "firebrick3"))(50))
compare_pheatmap(test, cluster_row = FALSE)
compare_pheatmap(test, legend = FALSE)
compare_pheatmap(test, display_numbers = TRUE)
compare_pheatmap(test, display_numbers = TRUE, number_format = "%.1e")
compare_pheatmap(test,
display_numbers = matrix(ifelse(test > 5, "*", ""), nrow(test)))
compare_pheatmap(test, cluster_row = FALSE, legend_breaks = -1:4,
legend_labels = c("0", "1e-4", "1e-3", "1e-2", "1e-1", "1"))
compare_pheatmap(test, cellwidth = 15, cellheight = 12, main = "Example heatmap")
annotation_col = data.frame(
CellType = factor(rep(c("CT1", "CT2"), 5)),
Time = 1:5
)
rownames(annotation_col) = paste("Test", 1:10, sep = "")
annotation_row = data.frame(
GeneClass = factor(rep(c("Path1", "Path2", "Path3"), c(10, 4, 6)))
)
rownames(annotation_row) = paste("Gene", 1:20, sep = "")
compare_pheatmap(test, annotation_col = annotation_col)
compare_pheatmap(test, annotation_col = annotation_col, annotation_legend = FALSE)
compare_pheatmap(test, annotation_col = annotation_col,
annotation_row = annotation_row)
compare_pheatmap(test, annotation_col = annotation_col,
annotation_row = annotation_row, angle_col = "45")
compare_pheatmap(test, annotation_col = annotation_col, angle_col = "0")
ann_colors = list(
Time = c("white", "firebrick"),
CellType = c(CT1 = "#1B9E77", CT2 = "#D95F02"),
GeneClass = c(Path1 = "#7570B3", Path2 = "#E7298A", Path3 = "#66A61E")
)
compare_pheatmap(test, annotation_col = annotation_col,
annotation_colors = ann_colors, main = "Title")
compare_pheatmap(test, annotation_col = annotation_col,
annotation_row = annotation_row, annotation_colors = ann_colors)
compare_pheatmap(test, annotation_col = annotation_col,
annotation_colors = ann_colors[2])
compare_pheatmap(test, annotation_col = annotation_col, cluster_rows = FALSE,
gaps_row = c(10, 14))
compare_pheatmap(test, annotation_col = annotation_col, cluster_rows = FALSE,
gaps_row = c(10, 14), cutree_col = 2)
labels_row = c("", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "Il10", "Il15", "Il1b")
compare_pheatmap(test, annotation_col = annotation_col, labels_row = labels_row)
drows = dist(test, method = "minkowski")
dcols = dist(t(test), method = "minkowski")
compare_pheatmap(test, clustering_distance_rows = drows,
clustering_distance_cols = dcols)
library(dendsort)
callback = function(hc, ...){dendsort(hc)}
compare_pheatmap(test, clustering_callback = callback)